# -*- coding: utf-8 -*-

from fastapi import APIRouter, status, Form, File, UploadFile, HTTPException
from pydantic import BaseModel, EmailStr
from typing import Optional, List, Union
chapter02 = APIRouter()

""" Response Model 响应模型 """


class UserIn(BaseModel):
    username: str
    password: str
    email: EmailStr
    mobile: str = "10086"
    address: str = None
    full_name: Optional[str] = None


class UserOut(BaseModel):
    username: str
    password: str
    email: EmailStr
    mobile: str = "10086"
    address: str = None
    full_name: Optional[str] = None


users = {
    "user01": {"username": "user01", "password": "123456", "email": "user01@example.com"},
    "user01": {"username": "user02", "password": "654321", "email": "user02@example.com"}
}

# 报错 pip install pydantic[email] ， 安装pip install email_validator
# response_model_exclude_unset 代表会覆盖响应对象的属性默认值
@chapter02.post('response_model', response_model=UserOut, response_model_exclude_unset=True)
async def response_model(user: UserIn):
    """
    response_model_exclude_unset 代表会覆盖响应对象的属性默认值
    :param user:
    :return:
    """
    return users["user01"]

@chapter02.post(
    '/response_model/attributes',
    # response_model=Union[UserIn, UserOut]
    # response_model_exclude=['username']
    # response_model_include=['username']
    response_model=List[UserOut]
)
async def response_model_attributes(user: UserIn):
    # 删除某个属性
    # del user.username
    return [user, user]

"""响应状态码"""
@chapter02.post('/status_code', status_code=200)
async def status_code():
    return {"status_code": 200}

@chapter02.post('/status_attribute', status_code=status.HTTP_200_OK)
async def status_attribute():
    print(type(status.HTTP_200_OK))
    return {"status_code": status.HTTP_200_OK}

"""Form Data 表单数据处理"""
@chapter02.post('/login')
async def login(username: str = Form(...), password: str = Form(...)):
    """
    用Form需要pip install python-multipart
    :param user:
    :param password:
    :return:
    """
    return {"username": username, "password": password}

"""Request Files 文件上传及参数详解"""
@chapter02.post('/file')
async def file_(file: bytes = File(...)):
    """
    使用File类，文件内容会以Bytes形式读入内存，适合上传小文件
    :param file:
    :return:
    """
    return {"file_size": len(file)}# 68776112

@chapter02.post('/files')
async def files(files: List[bytes] = File(...)):
    """
    上传多个文件，使用File类，文件内容会以Bytes形式读入内存，适合上传小文件
    :param files:
    :return:
    """
    return {"file_size": len(files)}

@chapter02.post('/upload_files')
async def upload_files(files: List[UploadFile] = File(...)):
    """
    使用UploadFile类的优势
    1.文件存储在内存中，使用内存达到阈值之后，将保存在磁盘中。
    2.适合图片，视频大文件
    3.可以获取上传的文件元数据，如文件名称， 时间
    4.有文件对象的异步接口
    5.上传的文件是Python文件对象，可以使用write(), read(), seek(), close()
    :param files:
    :return:
    """
    for file in files:
        contents = await file.read()
        print(contents)
    return {"filename": files[0].filename, "content_type": files[0].content_type}

"""见main.py   FastAPI项目静态文件配置"""

"""Path Operation Configuration 路径操作配置"""
@chapter02.post(
    '/path_operation_configuration',
    # tags=["Path", "Operation", "Configuration"],
    summary="This is summary",
    description="This is description",
    response_description="this is response description",
    deprecated=True,
    status_code=status.HTTP_200_OK
)
async def path_operation_configuration(user: UserIn):
    """
    Path Operation Configuration 路径操作配置
    :param user:
    :return:
    """
    return user.dict()

""" 见main.py FastAPI 应用常见配置项"""

""" Handling Errors 错误处理"""

@chapter02.get('http_exception')
async def http_exception(city: str):
    if city != "Beijing":
        raise HTTPException(status_code=404, detail="City Not Found", headers={"X-Error": "Error"})
    return {"city": city}

@chapter02.get('override_http_exception')
async def override_http_exception(city: str):
    if city != "Beijing":
        raise HTTPException(status_code=404, detail="City Not Found(Override Exception)", headers={"X-Error": "Override Error"})
    return {"city": city}
